package com.huawei.java.datahandle;

import com.huawei.java.model.ClientNode;
import com.huawei.java.model.Demand;
import com.huawei.java.model.Graph;
import com.huawei.java.model.SiteNode;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class CSVReader {
    private static final int SITE_NAME_INDEX = 0;

    private static final int SITE_BANDWIDTH_INDEX = 1;

    public static Graph readQOSFile() {
        Graph graph = new Graph();
        List<ClientNode> clientNodes = graph.getClientNodes();
        List<SiteNode> siteNodes = graph.getSiteNodes();
        Map<ClientNode, List<SiteNode>> clientMap = graph.getClientMap();
        Map<SiteNode, List<ClientNode>> siteMap = graph.getSiteMap();
        Map<String, SiteNode> siteIdMap = graph.getSiteIdMap();
        Map<String, ClientNode> clientIdMap = graph.getClientIdMap();
        Map<String, String> qosIni = readIniFile();
        int qosThreshold = Integer.parseInt(qosIni.get(FileConstant.QOS_CONSTRAINT));
        try (InputStream in = new FileInputStream(FileConstant.QOS_FILE_PATH);
             BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
            String line;
            int count = 0;
            while ((line = br.readLine()) != null) {
                count++;
                String[] siteToClients = line.split(FileConstant.COMMA);
                if (count == FileConstant.HEAD_INDEX) {
                    // handle head
                    for (int i = 1; i < siteToClients.length; i++) {
                        ClientNode clientNode = new ClientNode(siteToClients[i]);
                        clientNodes.add(clientNode);
                        clientIdMap.put(siteToClients[i], clientNode);
                    }
                    continue;
                }
                String siteName = siteToClients[SITE_NAME_INDEX];
                SiteNode currentSiteNode = new SiteNode(siteName);
                siteIdMap.put(siteName, currentSiteNode);
                siteNodes.add(currentSiteNode);
                for (int i = 1; i < siteToClients.length; i++) {
                    int currentQos = Integer.parseInt(siteToClients[i]);
                    if (currentQos >= qosThreshold) {
                        continue;
                    }
                    ClientNode clientNode = clientNodes.get(i - 1);
                    if (!clientMap.containsKey(clientNode)) {
                        clientMap.put(clientNode, new ArrayList<>());
                    }
                    clientMap.get(clientNode).add(currentSiteNode);

                    if (!siteMap.containsKey(currentSiteNode)) {
                        siteMap.put(currentSiteNode, new ArrayList<>());
                    }
                    siteMap.get(currentSiteNode).add(clientNode);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return graph;
    }

    private static Map<String, String> readIniFile() {
        Map<String, String> map = null;
        try (InputStream in = new FileInputStream(FileConstant.INI_FILE_PATH);
             BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))
        ) {
            Properties props = new Properties();
            props.load(br);
            map = new HashMap<>();
            for (Object s : props.keySet()) {
                map.put(s.toString(), props.getProperty(s.toString()));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }

    public static void readSiteBandwidthFile(Graph graph) {
        Map<String, SiteNode> siteIdMap = graph.getSiteIdMap();
        try (InputStream in = new FileInputStream(FileConstant.SITE_BANDWIDTH_FILE_PATH);
             BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
            String line;
            int count = 0;
            while ((line = br.readLine()) != null) {
                count++;
                if (count == FileConstant.HEAD_INDEX) {
                    continue;
                }
                String[] siteBandwidth = line.split(FileConstant.COMMA);
                String siteName = siteBandwidth[SITE_NAME_INDEX];
                SiteNode siteNode = siteIdMap.get(siteName);
                int bandwidth = Integer.parseInt(siteBandwidth[SITE_BANDWIDTH_INDEX]);
                siteNode.setTotalBandwidth(bandwidth);
                siteNode.setCurrentBandwidth(bandwidth);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static List<Demand> readDemandFile() {
        List<Demand> demandList = new ArrayList<>();
        try (InputStream in = new FileInputStream(FileConstant.DEMAND_FILE_PATH);
             BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
            String line;
            int count = 0;
            LinkedList<String> clientNameList = new LinkedList<>();
            while ((line = br.readLine()) != null) {
                count++;
                String[] clientDemands = line.split(FileConstant.COMMA);
                Demand demand = new Demand();
                Map<String, Integer> demandMap = demand.getDemandMap();
                if (count == FileConstant.HEAD_INDEX) {
                    clientNameList.addAll(Arrays.asList(clientDemands).subList(1, clientDemands.length));
                    continue;
                }
                demand.setTimestamp(clientDemands[0]);
                for (int i = 1; i < clientDemands.length; i++) {
                    String clientName = clientNameList.get(i - 1);
                    demandMap.put(clientName, Integer.parseInt(clientDemands[i]));
                }
                demandList.add(demand);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return demandList;
    }
}